#include "toolcreateline.h"
#include <Core>
#include <Line>
#include <Document>
#include "application.h"
#include "src/drawingview.h"
#include <QMouseEvent>

#include <QPushButton>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QGroupBox>
#include <QButtonGroup>
#include <QLabel>
#include <QLineEdit>

#include <AddLineCmd>

#include <cmath>

ToolCreateLine::ToolCreateLine(QObject *parent) :
    ToolCreate(parent)
{
}

QString ToolCreateLine::name() const
{
    return "Create Line";
}

QString ToolCreateLine::categoryName() const
{
    return "Create";
}

QString ToolCreateLine::iconPath() const
{
    return "resources\\icons\\createLine.png";
}

void ToolCreateLine::enter()
{
}

void ToolCreateLine::exit()
{
}

void ToolCreateLine::onMousePress(QMouseEvent *pEvent)
{
    QPointer<Document> activeDoc = Application::app().activeDocument();
    QPointer<DrawingView> activeView = qobject_cast<DrawingView*>(activeDoc->ownerView());
    Q_ASSERT(activeView);

    float oneOverZoom = 1.0f/activeDoc->zoom();

    if(!m_currentLine)
    {
        QPointF position = pEvent->posF()*oneOverZoom;
        QPointer<Line> newLine = activeDoc->createLine(position, position);
        m_currentLine = newLine;
        activeView->update();
    }
}

void ToolCreateLine::onMouseMove(QMouseEvent *pEvent)
{
    QPointer<Document> activeDoc = Application::app().activeDocument();
    QPointer<DrawingView> activeView = qobject_cast<DrawingView*>(activeDoc->ownerView());
    Q_ASSERT(activeView);

    float oneOverZoom = 1.0f/activeDoc->zoom();

    if(m_currentLine)
    {
        QPointF position = pEvent->posF()*oneOverZoom;
        m_currentLine->setEnd(position);
        activeView->update();
    }
}

void ToolCreateLine::onMouseRelease(QMouseEvent *pEvent)
{
    QPointer<Document> activeDoc = Application::app().activeDocument();
    QPointer<DrawingView> activeView = qobject_cast<DrawingView*>(activeDoc->ownerView());
    Q_ASSERT(activeView);

    if(m_currentLine)
    {
        if(m_currentLine->length() < 5.0f)
        {
            m_currentLine = 0;
            activeView->update();
        }
        else
        {
            AddLineCmd* pCmd = new AddLineCmd(*activeDoc, m_currentLine);
            activeDoc->undoStack()->push(pCmd);
            m_currentLine = 0;
        }
    }
}

void ToolCreateLine::draw()
{
    if(m_currentLine)
    {
        m_currentLine->draw();

        boost::shared_ptr<Renderer> renderer = Core::instance().renderer();
        QPointF unitVec = m_currentLine->unitVector();
        float angle = atan2(unitVec.y(), unitVec.x());

        if(angle > 0)
        {
            angle -= 2*3.14f;
        }

        renderer->drawCircle(m_currentLine->start(), m_currentLine->length()/3, 0, angle, Qt::white);

        Renderer::LineStyle dotedLine;
        dotedLine.factor = 2;
        dotedLine.pattern = 0xAAAA;

        QPointF end;
        end.setX(m_currentLine->start().x()
                 + max(m_currentLine->length()/3, fabs(m_currentLine->length()*cos(angle))));
        end.setY(m_currentLine->start().y());

        renderer->drawLine(m_currentLine->start(), end, Qt::white, 1, &dotedLine);

        QPointer<Document> activeDoc = Application::app().activeDocument();
        Q_ASSERT(activeDoc);
        QPointer<DrawingView> activeView = qobject_cast<DrawingView*>(activeDoc->ownerView());
        Q_ASSERT(activeView);

        int textX = m_currentLine->start().x() + (m_currentLine->length()/3 + 30)*cos(angle/2.0f);
        int textY = m_currentLine->start().y() + (m_currentLine->length()/3 + 30)*sin(angle/2.0f);

        float angleToShow = -angle*180/3.14f;
        activeView->renderText(textX, textY, QString("%1").arg(angleToShow));
    }
}

void ToolCreateLine::initPropertiesWidget()
{
    m_propertiesWidget = new QGroupBox("Create Line Properties");
    QVBoxLayout* pMainVerticalLayout = new QVBoxLayout(m_propertiesWidget);

    m_startX = new QLineEdit;
    m_startY = new QLineEdit;
    m_endX = new QLineEdit;
    m_endY = new QLineEdit;

    QGroupBox* startGroup = new QGroupBox("Start");
    QHBoxLayout* pStartHLayout = new QHBoxLayout(startGroup);
    pStartHLayout->addWidget(new QLabel("X:"));
    pStartHLayout->addWidget(m_startX);
    pStartHLayout->addWidget(new QLabel("Y:"));
    pStartHLayout->addWidget(m_startY);

    pMainVerticalLayout->addWidget(startGroup);

    QGroupBox* endGroup = new QGroupBox("End");
    QHBoxLayout* pEndHLayout = new QHBoxLayout(endGroup);
    pEndHLayout->addWidget(new QLabel("X:"));
    pEndHLayout->addWidget(m_endX);
    pEndHLayout->addWidget(new QLabel("Y:"));
    pEndHLayout->addWidget(m_endY);

    pMainVerticalLayout->addWidget(endGroup);

    m_buttonCreate = new QPushButton("Create");
    pMainVerticalLayout->addWidget(m_buttonCreate);
    m_buttonCreate->setEnabled(false);

    connect(m_buttonCreate, SIGNAL(clicked()), this, SLOT(onCreateLineParametric()));
    connect(m_startX, SIGNAL(textChanged(QString)), this, SLOT(onTextChanged(QString)));
    connect(m_startY, SIGNAL(textChanged(QString)), this, SLOT(onTextChanged(QString)));
    connect(m_endX, SIGNAL(textChanged(QString)), this, SLOT(onTextChanged(QString)));
    connect(m_endY, SIGNAL(textChanged(QString)), this, SLOT(onTextChanged(QString)));
}

void ToolCreateLine::onCreateLineParametric()
{
    QPointer<Document> activeDoc = Application::app().activeDocument();
    Q_ASSERT(activeDoc);
    QPointer<DrawingView> activeView = qobject_cast<DrawingView*>(activeDoc->ownerView());
    Q_ASSERT(activeView);

    QPointF start(m_startX->text().toDouble(), m_startY->text().toDouble());
    QPointF end(m_endX->text().toDouble(), m_endY->text().toDouble());

    QPointer<Line> newLine = activeDoc->createLine(start, end);
    AddLineCmd* pCmd = new AddLineCmd(*activeDoc, newLine);
    activeDoc->undoStack()->push(pCmd);
}

void ToolCreateLine::onTextChanged(const QString &text)
{
    bool bEnableCreate = !( m_startX->text().isEmpty() ||
                            m_startY->text().isEmpty() ||
                            m_endX->text().isEmpty() ||
                            m_endY->text().isEmpty() );

    m_buttonCreate->setEnabled(bEnableCreate);
}
